#__author__=='qustl_000'
#-*- coding: utf-8 -*-

from sklearn import neighbors
from numpy import *
import operator
import random

'''python实现KNN，返回列表类型的数据集'''
def createDataSet(filename,split):
    trainingSet = []
    testSet = []
    with open(filename) as csvfile:
       lines=csvfile.readlines()
       for line in lines:
            lineData=line.strip().split(',')
            if random.random() < split:
                trainingSet.append(lineData)
            else:
                testSet.append(lineData)
    return trainingSet,testSet

'''获取数据的特征值和标签值,返回np.narray类型的数据集'''
def dataLabel(dataSet):
    data=[]
    label=[]
    for x in range(len(dataSet)-1):
        data.append([float(tk) for tk in dataSet[x][:-1]])
        label.append(dataSet[x][-1])
    return array(data),array(label)

def classify0(inX,dataSet,label,k):
    #返回“数组”的行数，如果shape[1]返回的则是数组的列数
    dataSetSize=dataSet.shape[0]
    #计算待分类数据与已知数据间的差值，tile函数为扩充函数,在行方向上重复dataSize次
    diffMat=tile(inX,(dataSetSize,1))-dataSet

    #求平方
    sqDiffMat=diffMat**2
    #求和,矩阵的每一行相加axis=1
    Distances=sqDiffMat.sum(axis=1)
    #求开方
    sqrtDis=Distances**0.5
    #排序，原数组从小到大排序,并返回其原索引值
    sortedIndex=sqrtDis.argsort()
    #定义一个空字典
    classCount={}
    for i in range(k):
        #返回距离最近的k个点所对应的标签值
        voteILabel=label[sortedIndex[i]]
        #存放到字典中,get(key,defalut=None)函数查找键值key的值，若不存在则返回的defalut的值
        classCount[voteILabel]=classCount.get(voteILabel,0)+1
        #排序 classCount.iteritems()
        sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

'''****************************sklearn 实现KNN*****************************'''

'''****************用于找到最近的邻居*****************'''
from sklearn.neighbors import NearestNeighbors

#定义一个数组
X_train=array([[-1,-1],[-2,-1],[-3,-2],[1,1],[2,1],[3,2]])
x_test=array([[-1,1],[-1,0]])
def findNeighbors():
    '''
    NearestNeibors参数解释：
    （1）n_neighbors=5，默认值为5，表示查询k个最近邻的数目
    （2）algorithm='auto'，指定用于计算最近邻的算法，auto表示用最合适的算法计算最近邻
    （3）fit(x)表示用X来训练算法
    '''
    nbrs=NearestNeighbors(n_neighbors=3,algorithm='ball_tree').fit(X_train)
    #返回距离每个点k个最近的点和距离指数,indics可以理解为表示点的下标，distancestor为距离
    distances,indices=nbrs.kneighbors(x_test)
    print(distances)
    print(indices)
    #输出的是求解n个最近邻点后的矩阵图，1表示是最近邻点，0表示不是最近邻点
    print(nbrs.kneighbors_graph(x_test).toarray())

'''********************测试KDTree*********************'''
def TestKDtree():
    from sklearn.neighbors import KDTree
    '''
    leaf_size:叶子的个数
    metric：计算距离的方法，默认为minkowski,如欧拉法euclidean
    '''
    kdtree=KDTree(X_train,leaf_size=30,metric='euclidean')
    print(kdtree.query(x_test,k=3,return_distance=False))

'''********************测试BallTree*********************'''
def TestBallTree():
    from sklearn.neighbors import BallTree
    Btree=BallTree(X_train,leaf_size=30,metric='euclidean')
    print(Btree.query(x_test,k=3,return_distance=False))

'''********************Sklearn kNN分类实例*********************'''
def classifyIris():
    from sklearn.datasets import load_iris
    
    from sklearn import neighbors
    import sklearn

    #查看iris数据集
    iris=load_iris()
    #print(iris)
    '''
    KNeighborsClaaifier(n_neighbors=5, weights=’uniform’, algorithm=’auto’,
                        leaf_size=30, p=2, metric=’minkowski’, metric_params=None,
                        n_jobs=1, **kwargs)
    '''
    knn=neighbors.KNeighborsClassifier(n_neighbors=3,algorithm='kd_tree')
    #训练数据集
    knn.fit(iris.data,iris.target)
    #分类
    predict=knn.predict([[0.1,0.2,0.3,0.4]])
    print(predict)
    print(iris.target_names[predict])



